﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using XRpgLibrary.TileEngine;

namespace XLevelEditor.Controls
{
    class TileSelector : MapDisplay
    {
        Texture2D tilesetTexture = null;
        public Texture2D TilesetTexture 
        {
            get
            {
                return tilesetTexture;
            }
            set
            {
                tilesetTexture = value;
                tilesWide = -1;
                tilesHigh = -1;
                if (value != null)
                {
                    Width = value.Width;
                    Height = value.Height;
                }
            }
        }
        
        Texture2D cursorTexture = null;
        Texture2D CursorTexture
        {
            get
            {
                if (cursorTexture == null)
                {
                    cursorTexture = new Texture2D(GraphicsDevice, 1, 1);
                    cursorTexture.SetData<Color>(new Color[] { new Color(0, 0, 255, 25) });
                }

                return cursorTexture;
            }
        }
        SpriteBatch spriteBatch;

        Point CurrentTile
        {
            get
            {
                return new Point(
                    mousePosition.X / Engine.TileWidth,
                    mousePosition.Y / Engine.TileHeight);
            }
        }

        public int CurrentTileIndex
        {
            get
            {
                return ((TileSource.Y / Engine.TileHeight) * TilesWide) + (TileSource.X / Engine.TileWidth);
            }
        }

        Point SelectionStartTile;
        
        int tilesWide = -1;
        public int TilesWide
        {
            get
            {
                if (tilesWide < 0)
                    tilesWide = TilesetTexture.Width / Engine.TileWidth;

                return tilesWide;
            }
        }

        int tilesHigh = -1;
        public int TilesHigh
        {
            get
            {
                if (tilesHigh < 0)
                    tilesHigh = TilesetTexture.Height / Engine.TileHeight;

                return tilesHigh;
            }
        }

        Rectangle cursorRect;
        public Rectangle TileSource
        {
            get
            {
                return cursorRect;
            }
        }

        Rectangle sourceRect;
        Rectangle destRect;

        Timer timer;

        bool leftClick = false;
        Point mousePosition;



        public TileSelector()
        {

        }

        void  timer_Tick(object sender, EventArgs e)
        {
            Update();
        }

        protected override void Initialize()
        {
            base.Initialize();

            spriteBatch = new SpriteBatch(GraphicsDevice);
            cursorRect = new Rectangle(0, 0, Engine.TileWidth, Engine.TileHeight);
            timer = new Timer();
            timer.Interval = 25;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Enabled = true;
            mousePosition = new Point(0, 0);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            mousePosition.X = e.X;
            mousePosition.Y = e.Y;

            this.Invalidate();
            
            base.OnMouseMove(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                SelectionStartTile = CurrentTile;
                leftClick = true;
            }

            this.Invalidate();

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                leftClick = false;

            this.Invalidate();

            base.OnMouseUp(e);
        }

        protected new void Update()
        {
            if (leftClick)
                cursorRect = BuildCursorRect();

            base.Update();
        }

        protected override void Draw()
        {
            if (TilesetTexture == null)
                return;

            GraphicsDevice.Clear(Color.White);

            spriteBatch.Begin();

            spriteBatch.Draw(
                TilesetTexture,
                new Rectangle(0, 0, TilesetTexture.Width, TilesetTexture.Height),
                TilesetTexture.Bounds, 
                Color.White);

            DrawCursor();
            
            spriteBatch.End();

            base.Draw();
        }

        private void DrawCursor()
        {
            spriteBatch.Draw(CursorTexture, cursorRect, Color.White);
        }

        private Rectangle BuildCursorRect()
        {
            int top = Math.Min(SelectionStartTile.Y, CurrentTile.Y);
            int left = Math.Min(SelectionStartTile.X, CurrentTile.X);
            int width = Math.Abs(SelectionStartTile.X - CurrentTile.X) + 1;
            int height = Math.Abs(SelectionStartTile.Y - CurrentTile.Y) + 1;

            return new Rectangle(
                left * Engine.TileWidth,
                top * Engine.TileHeight,
                width * Engine.TileWidth,
                height * Engine.TileHeight);
        }

        public Tile[,] GetSelectedMatrix(int tileSetIndex)
        {
            Tile[,] matrix = new Tile[(cursorRect.Height / Engine.TileHeight),
                                      (cursorRect.Width / Engine.TileWidth)];

            for (int y = 0, ycnt = matrix.GetLength(0); y < ycnt; y++)
                for (int x = 0, xcnt = matrix.GetLength(1); x < xcnt; x++)
                    matrix[y, x] = new Tile(
                        ((y + (TileSource.Y / Engine.TileHeight)) * TilesWide) + (x + (TileSource.X / Engine.TileWidth)));

            return matrix;
        }
    }
}